'''
多模态视觉模型与工具调用示例

核心功能：
1. 多模态理解：让大模型同时处理文本和图像信息
2. 工具调用：模型可以决定调用外部工具来处理特定任务
3. 视觉问答：基于图像内容进行问答和描述

技术要点：
- 视觉语言模型（VL Model）：能够理解图像和文本的模型
- 工具绑定：让模型具备调用外部函数的能力
- 多消息格式：支持文本、图像等多种内容类型
'''
import os
# Literal 在函数签名上只是类型提示（且在某些工具注册/解析流程中，会被框架读取用于自动校验或生成 schema），但不要完全依赖它来"约束"LLM 输出
from typing import Literal

from dotenv import load_dotenv
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

# 自动加载 .env 文件中的环境变量
load_dotenv()


@tool
def weather_tool(weather: Literal["晴朗", "多云", "下雨天", "下雪天", "阴天"]) -> None:
    """
    天气描述工具函数

    功能：接收模型识别的天气类型，执行相应的业务逻辑
    设计理念：让专业的事情交给专业工具处理

    参数：
        weather: 天气类型，限定在预定义的几种类型中
                使用Literal类型提示，帮助框架生成准确的schema

    实际应用场景：
        - 更新天气数据库
        - 触发天气相关业务逻辑
        - 发送天气通知
        - 记录天气统计信息
    """
    # 在实际应用中，这里会包含具体的业务逻辑
    # 例如：更新数据库、调用天气API、发送通知等
    print(f"🌤️  天气工具被调用: {weather}")
    # 这里可以添加实际的业务逻辑
    pass


# ========== 初始化视觉语言模型 ==========
'''
视觉语言模型（Vision-Language Model）特点：
- 能够同时理解图像和文本内容
- 支持多模态输入（文字、图片、可能还有音频、视频等）
- 可以基于图像内容进行推理和回答
'''
# VL 表示是视觉模型（Vision-Language）
llm = ChatOpenAI(api_key=os.getenv("MODELSCOPE_API_KEY"), openai_api_base=os.getenv("MODELSCOPE_API_BASE"), model="Qwen/Qwen2.5-VL-72B-Instruct", streaming=True, temperature=0)

# ========== 工具绑定 ==========
'''
工具绑定的作用：
1. 扩展模型能力：让模型可以调用外部工具
2. 专业化处理：特定任务交给专用工具处理
3. 结构化输出：工具调用提供结构化的交互方式

工作流程：
1. 模型分析输入（文本+图像）
2. 模型判断是否需要调用工具
3. 如果需要，生成工具调用请求
4. LangChain执行工具调用
5. 工具结果返回给模型继续处理
'''
llm_with_tools = llm.bind_tools([weather_tool])

# ========== 图像数据准备 ==========
'''
图像URL说明：
- 使用公开可访问的图像URL
- 支持多种图像格式（JPEG、PNG等）
- 可以是网络图片或base64编码的图片数据
'''
# 定义需要处理的图片地址
image_url_1 = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage109.360doc.com%2FDownloadImg%2F2025%2F04%2F0321%2F296122601_4_20250403090445718&refer=http%3A%2F%2Fimage109.360doc.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1762504985&t=8090aac3171f1a36b1433b4888b8722f"
image_url_2 = "https://img1.baidu.com/it/u=4167756712,354011797&fm=253&app=138&f=JPEG?w=800&h=1067"

print("🖼️  使用的图像URL:")
print(f"   图像1: {image_url_1}")
print(f"   图像2: {image_url_2}")

# ========== 构建多模态消息 ==========
'''
HumanMessage 支持多内容类型：
- text: 文本内容
- image_url: 图像URL或base64数据
- 其他类型：audio、video等（取决于模型支持）

消息结构说明：
content 是一个列表，可以包含多种类型的内容块
这种设计让模型能够同时处理多种模态的输入
'''
message = HumanMessage(
    content=[
        {"type": "text", "text": "用中文描述图中的天气"},  # 文本指令
        {"type": "image_url", "image_url": {"url": image_url_2}},  # 第一张图片
        {"type": "image_url", "image_url": {"url": image_url_1}}  # 第二张图片
    ]
)

print("\n📨 构建的多模态消息:")
print(f"   文本指令: 用中文描述图中的天气")
print(f"   图像数量: 2张")
print(f"   消息类型: HumanMessage")

# ========== 调用模型并处理响应 ==========
print("\n🚀 开始调用视觉语言模型...")
response = llm_with_tools.invoke([message])

# ========== 分析模型响应 ==========
print("\n📊 模型响应分析:")
print(f"   响应类型: {type(response)}")
print(f"   是否有工具调用: {bool(response.tool_calls)}")

if response.tool_calls:
    print("🎯 模型决定调用工具:")
    for i, tool_call in enumerate(response.tool_calls, 1):
        print(f"   工具调用 {i}:")
        print(f"     工具名称: {tool_call['name']}")
        print(f"     工具参数: {tool_call['args']}")

        # 在实际应用中，这里会执行真正的工具调用
        # 例如：weather_tool.invoke(tool_call['args'])
else:
    print("📝 模型直接回复（未调用工具）:")
    print(f"   回复内容: {response.content}")


# ========== 完整工具调用流程演示 ==========
def demonstrate_complete_tool_workflow():
    """
    演示完整的工具调用工作流程
    """
    print("\n" + "=" * 60)
    print("🔧 完整工具调用工作流程演示")
    print("=" * 60)

    # 模拟工具调用的完整流程
    if response.tool_calls:
        for tool_call in response.tool_calls:
            tool_name = tool_call['name']
            tool_args = tool_call['args']

            print(f"\n1. 🧠 模型分析图像内容")
            print(f"2. 🔍 识别到需要调用工具: {tool_name}")
            print(f"3. 📋 生成工具参数: {tool_args}")
            print(f"4. ⚡ 执行工具调用...")

            # 实际执行工具调用
            if tool_name == "weather_tool":
                weather_tool.invoke(tool_args)
                print(f"5. ✅ 工具调用完成")
                print(f"6. 🔄 可以将工具结果返回给模型继续处理")


# 运行完整流程演示
demonstrate_complete_tool_workflow()


# ========== 进阶功能：多模态应用场景 ==========
def demonstrate_advanced_use_cases():
    """
    演示多模态模型的高级应用场景
    """
    print("\n" + "=" * 60)
    print("🎯 多模态模型应用场景")
    print("=" * 60)

    scenarios = [
        {
            "name": "天气识别",
            "prompt": "分析图片中的天气状况，并调用天气工具",
            "use_case": "智能气象监测"
        },
        {
            "name": "物体识别",
            "prompt": "识别图片中的主要物体和场景",
            "use_case": "智能安防、图像分类"
        },
        {
            "name": "情感分析",
            "prompt": "分析图片中人物的情感状态",
            "use_case": "心理分析、用户体验研究"
        },
        {
            "name": "场景理解",
            "prompt": "描述图片中的场景和活动",
            "use_case": "内容审核、场景分析"
        }
    ]

    for scenario in scenarios:
        print(f"\n📖 {scenario['name']}:")
        print(f"   提示词: {scenario['prompt']}")
        print(f"   应用场景: {scenario['use_case']}")


# 运行进阶场景演示
demonstrate_advanced_use_cases()


# ========== 错误处理和最佳实践 ==========
def demonstrate_error_handling():
    """
    演示错误处理和改进实践
    """
    print("\n" + "=" * 60)
    print("⚠️  错误处理和最佳实践")
    print("=" * 60)

    print("\n🔧 工具设计的改进建议:")
    print("   1. 添加参数验证")
    print("   2. 实现错误处理机制")
    print("   3. 添加日志记录")
    print("   4. 考虑异步处理")

    print("\n🖼️  图像处理的最佳实践:")
    print("   1. 验证图像URL可访问性")
    print("   2. 处理图像加载失败情况")
    print("   3. 考虑图像大小和格式限制")
    print("   4. 实现图像缓存机制")

    print("\n🤖 模型调用的优化建议:")
    print("   1. 设置合理的超时时间")
    print("   2. 实现重试机制")
    print("   3. 监控API使用情况")
    print("   4. 处理速率限制")


# 运行错误处理演示
demonstrate_error_handling()

print("\n" + "=" * 60)
print("🎉 多模态图像处理演示完成!")
print("=" * 60)
print("💡 核心技术要点总结:")
print("   1. 🌟 视觉语言模型支持图文多模态输入")
print("   2. 🔧 工具调用扩展模型能力边界")
print("   3. 🖼️  HumanMessage支持复杂内容结构")
print("   4. 🤖 模型自主决定是否调用工具")
print("   5. 🔄 LangChain自动管理工具调用流程")
